home *** CD-ROM | disk | FTP | other *** search
/ Delphi Informant Complete 1995 - 2000 / Delphi Informant Complete 1995 to 2000.iso / Delphi Informant Magazine Complete Works SOURCE CODE 1998.rar / 1998 / Aug / DI9808AM / Tapiu_2.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1998-06-09  |  25.7 KB  |  700 lines

  1. { This project accompanies the second article written by Alan Moore
  2.   and Ken Kyler on TAPI }
  3.  
  4. unit Tapiu_2;
  5.  
  6. interface
  7.  
  8. uses
  9.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  10.   StdCtrls, ExtCtrls, Mask, ComCtrls, Buttons, CommStatus, Tapi;
  11.  
  12. type
  13.   TForm1 = class(TForm)
  14.     PanelTop: TPanel;
  15.     Label1: TLabel;
  16.     ePhoneNum: TMaskEdit;
  17.     btnDial: TButton;
  18.     btnHangup: TButton;
  19.     cboxDevices: TComboBox;
  20.     cbLineMapper: TCheckBox;
  21.     Memo: TMemo;
  22.     StatusBar: TPanel;
  23.     ImageList: TImageList;
  24.     cboxMediaMode: TComboBox;
  25.     cboxBearerMode: TComboBox;
  26.     Panel1: TPanel;
  27.     RI: TImage;
  28.     CD: TImage;
  29.     RD: TImage;
  30.     DSR: TImage;
  31.     DTR: TImage;
  32.     CTS: TImage;
  33.     Label2: TLabel;
  34.     Label3: TLabel;
  35.     Label4: TLabel;
  36.     Label5: TLabel;
  37.     Label6: TLabel;
  38.     Label7: TLabel;
  39.     Port: TImage;
  40.     Label8: TLabel;
  41.     btnDialingProperties: TButton;
  42.     procedure btnDialClick(Sender: TObject);
  43.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  44.     procedure FormCreate(Sender: TObject);
  45.     procedure btnHangupClick(Sender: TObject);
  46.     procedure cboxDevicesChange(Sender: TObject);
  47.     procedure cbLineMapperClick(Sender: TObject);
  48.     procedure cboxMediaModeChange(Sender: TObject);
  49.     procedure cboxBearerModeChange(Sender: TObject);
  50.     procedure btnDialingPropertiesClick(Sender: TObject);
  51.   private
  52.     { Private declarations }
  53.     FCommStatusThread: TCommStatus;
  54.     FTapiInitialized : Boolean;
  55.     function  TapiInitialize: boolean;
  56.     procedure CreateCallManager;
  57.     // really a bad description!  The whole application is the call manager
  58.     procedure EnumerateDevices;
  59.     // added 11 Jan 98
  60. //=========================================================
  61.     procedure ModemOff;
  62.     function  GetPortHandle : THandle;
  63.     // added by Alan 6 April 98
  64.     procedure ShowLineTranslateDialog(Sender: TObject);
  65. // =====================================================================
  66.  
  67.   public
  68.     { Public declarations }
  69.     { Because ShutdownCallManager is called from the CallBack function,
  70.       ShutdownCallManager must be declared public }
  71.     function  ShutdownCallManager: boolean;
  72.     procedure SetBitmap(Image: TImage; Index: integer);
  73.   end;
  74.  
  75. var
  76.   Form1: TForm1;
  77.   FLineApp: HLINEAPP;
  78.   FNumDevs,
  79.   FVersion: Integer;
  80.   FMediaMode,
  81.   FBearerMode: DWord;
  82.   FExt: TLINEEXTENSIONID;
  83.   FLine: HLINE;
  84.   FLineCallParams: TLineCallParams;
  85.   FLineOpen: boolean;
  86.   FHCall: HCALL;
  87.   FCountryCode: integer;
  88.   FDev: integer; //value of device ID to initialize, 0..NumDevs }
  89.   FPort: THandle; // handle of the opened port - new 18 Jan 98
  90.   FCanonicalPhNum : LPCSTR; // canonical phone number  - 23 April 1998
  91.   FLineTranslateOptions : DWord;
  92.   lpTranslateOutput : LPLINETRANSLATEOUTPUT;
  93.  
  94. implementation
  95.  
  96. {$R *.DFM}
  97.  
  98. const
  99.   Ver = $00010004;  // API version accepted (1.4) [Windows 95]
  100.   off = 0;
  101.   red = 1;
  102.   yellow = 2;
  103.   green = 3;
  104.  
  105. // Local Functions -------------------------------------------------------------
  106. procedure LineCallBack(hDevice, dwMessage, dwInstance, dwParam1, dwParam2,
  107.   dwParam3 : DWORD); stdcall; // handles messages from the line
  108. begin
  109.   with Form1, Memo.Lines do begin
  110.      case dwMessage of
  111.        LINE_CALLSTATE: begin //reports asynchronous responses
  112.           case dwParam1 of
  113.              LINECALLSTATE_IDLE: begin
  114.                 Add('LCB (LINE_CALLSTATE): The call is idle - ' +
  115.                   ' no call actually exists.');
  116.                 ShutdownCallManager;
  117.              end;
  118.              LINECALLSTATE_OFFERING:
  119.                 Add('LCB (LINE_CALLSTATE): ' +
  120.                   ' The call is being offered to the station.');
  121.              LINECALLSTATE_ACCEPTED:
  122.                 Add('LCB (LINE_CALLSTATE): ' +
  123.                   ' The call was offering and has been accepted.');
  124.              LINECALLSTATE_DIALTONE: begin
  125.                 // added 14 Jan 98 ============================================
  126.                 ImageList.GetBitMap(green, CD.Picture.Bitmap);
  127.                 // ============================================================
  128.                 Add('LCB (LINE_CALLSTATE): The call is receiving a dial tone.');
  129.              end;
  130.              LINECALLSTATE_DIALING:
  131.                 Add('LCB (LINE_CALLSTATE): Dialing ' + Form1.ePhoneNum.Text);
  132.              LINECALLSTATE_RINGBACK:
  133.                 Add('LCB (LINE_CALLSTATE): The call is receiving ringback.');
  134.              LINECALLSTATE_BUSY: begin // note, difficult to detect
  135.                 case dwParam2 of
  136.                    LINEBUSYMODE_STATION:
  137.                       Add('LCB (LINE_CALLSTATE): ' +
  138.                         'Busy signal; called party''s station is busy.');
  139.                    LINEBUSYMODE_TRUNK:
  140.                       Add('LCB (LINE_CALLSTATE): ' +
  141.                         'Busy signal; trunk or circuit is busy.');
  142.                    LINEBUSYMODE_UNKNOWN:
  143.                       Add('LCB (LINE_CALLSTATE): ' +
  144.                         ' Busy signal; specific mode is currently unkown');
  145.                    LINEBUSYMODE_UNAVAIL:
  146.                       Add('LCB (LINE_CALLSTATE): ' +
  147.                         ' Busy signal; specific mode is unavailable');
  148.                 else
  149.                    Add('LCB (LINE_CALLSTATE): ' +
  150.                      ' The call is receiving an unidentifiable busy tone.');
  151.                 end;
  152.                 ShutdownCallManager;
  153.              end;
  154.              LINECALLSTATE_SPECIALINFO:
  155.                 Add('LCB (LINE_CALLSTATE): ' +
  156.                   ' Special information is sent by the network.');
  157.              LINECALLSTATE_CONNECTED:
  158.                 Add('LCB (LINE_CALLSTATE): ' +
  159.                   ' The call has been established and the connection is made.');
  160.              LINECALLSTATE_PROCEEDING:
  161.                 Add('LCB (LINE_CALLSTATE): ' +
  162.                   ' Dialing has completed and the call is proceeding.');
  163.              LINECALLSTATE_ONHOLD:
  164.                 Add('LCB (LINE_CALLSTATE): The call is on hold by the switch.');
  165.              LINECALLSTATE_CONFERENCED:
  166.                 Add('LCB (LINE_CALLSTATE): The call is currently ' +
  167.                   ' a member of a multi-party conference call.');
  168.              LINECALLSTATE_ONHOLDPENDCONF:
  169.                 Add('LCB (LINE_CALLSTATE): The call is currently ' +
  170.                   ' on hold while it is being added to a conference.');
  171.              LINECALLSTATE_DISCONNECTED: begin
  172.                 Add('LCB (LINE_CALLSTATE): The line has been disconnected.');
  173.                 case dwParam2 of
  174.                    LINEDISCONNECTMODE_NORMAL:
  175.                       Add(#9 + 'This is a "normal" disconnect request.');
  176.                    LINEDISCONNECTMODE_UNKNOWN:
  177.                       Add(#9 + 'The reason for the disconnect ' +
  178.                         ' request is unknown.');
  179.                    LINEDISCONNECTMODE_REJECT:
  180.                       Add(#9 + 'The remote user has rejected the call.');
  181.                    LINEDISCONNECTMODE_PICKUP:
  182.                       Add(#9 + 'The call was picked up from elsewhere.');
  183.                    LINEDISCONNECTMODE_FORWARDED:
  184.                       Add(#9 + 'The call was forwarded by the switch.');
  185.                    LINEDISCONNECTMODE_BUSY:
  186.                       Add(#9 + 'The remote user''s station is busy.');
  187.                    LINEDISCONNECTMODE_NOANSWER:
  188.                       Add(#9 + 'The remote user''s station does not answer.');
  189.                    LINEDISCONNECTMODE_BADADDRESS:
  190.                       Add(#9 + 'The destination address in invalid.');
  191.                    LINEDISCONNECTMODE_UNREACHABLE:
  192.                       Add(#9 + 'The remote user could not be reached.');
  193.                    LINEDISCONNECTMODE_CONGESTION:
  194.                       Add(#9 + 'The network is congested.');
  195.                    LINEDISCONNECTMODE_INCOMPATIBLE:
  196.                       Add(#9 + 'The remote user''s station equipment ' +
  197.                         ' is incompatible');
  198.                    LINEDISCONNECTMODE_UNAVAIL:
  199.                       Add(#9 + 'The reason for the disconnect is unavailable');
  200.                 end;
  201.              end;
  202.              LINECALLSTATE_UNKNOWN:
  203.                Add('LCB (LINE_CALLSTATE): The state of the call is not known.');
  204.              end;
  205.           end;
  206.        LINE_LINEDEVSTATE:
  207.           case dwParam1 of // incomplete list
  208.              LINEDEVSTATE_RINGING:
  209.                 Add('LCB (LINE_LINEDEVSTATE): (Ringing) Ring, ring, ring...');
  210.              LINEDEVSTATE_CONNECTED:
  211.                 Add('LCB (LINE_LINEDEVSTATE): Connected...');
  212.              LINEDEVSTATE_DISCONNECTED:
  213.                 Add('LCB (LINE_LINEDEVSTATE): Disconnected.');
  214.              LINEDEVSTATE_REINIT: // line device has changed or been modified
  215.                 if (dwParam2 = 0) then begin
  216.                    Add('LCB (LINE_LINEDEVSTATE): Shutdown required');
  217.                    ShutdownCallManager;
  218.                 end;
  219.           end;
  220.        LINE_REPLY:
  221.           if (dwParam2 = 0) then begin
  222.              Add('LCB (LINE_REPLY): LineMakeCall completed successfully');
  223.              SetBitMap(DTR, green);
  224.           end
  225.           else
  226.              Add('LCB (LINE_REPLY): LineMakeCall failed');
  227.     end;
  228.   end;
  229. end;
  230.  
  231. function RecordGetStr (var Data; Field : Pointer) : string;
  232. var
  233.   Len: Longint;
  234. begin
  235.   Len := PInt(Field)^; // PInt is defined in Windows.pas
  236.   Inc(PInt(Field));
  237.   if (PInt(Field)^ <> 0) then
  238.      SetString(Result, PChar(Longint(@Data) + PInt(Field)^), Len - 1)
  239.   else
  240.      Result := '';
  241. end;
  242. //-- End of Local Functions ----------------------------------------------------
  243.  
  244. procedure TForm1.btnDialClick(Sender: TObject);
  245. begin
  246.   if not cbLineMapper.Checked and (FDev < 0) then begin // a device wasn't selected
  247.      ShowMessage('You must first select a Line device!');
  248.      Exit;
  249.   end;
  250.   btnDial.Enabled := false;  // disable the dial button
  251.   btnHangup.Enabled := true; // and enable the hangup button
  252.   CreateCallManager;
  253.   // 14 Jan 98 - changed to line make call
  254. end;
  255.  
  256. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  257. begin
  258.   // if the custom call manager was used, make sure to free resources
  259.   if FLineOpen then
  260.      CanClose := ShutdownCallManager;
  261. end;
  262.  
  263. function TForm1.TapiInitialize: boolean;
  264. var
  265.   ErrNo: Longint;
  266.   S: string;
  267. begin
  268.   Result := false;
  269.   // Initialize TAPI for use by custom call manager
  270.   FCountryCode := 0;
  271.   FVersion := 0;
  272.   ErrNo := LineInitialize(@FLineApp, MainInstance, LineCallback, '', @FNumDevs);
  273.   case ErrNo of
  274.      0: Begin
  275.         Memo.Lines.Add('LineInitialize was successful');
  276.         FTapiInitialized := true;
  277.         end;
  278.      LINEERR_INVALAPPNAME: S := 'LINEERR_INVALAPPNAME';
  279.      LINEERR_OPERATIONFAILED: S := 'LINEERR_OPERATIONFAILED';
  280.      LINEERR_INIFILECORRUPT: S := 'LINEERR_INIFILECORRUPT';
  281.      LINEERR_RESOURCEUNAVAIL: S := 'LINEERR_RESOURCEUNAVAIL';
  282.      LINEERR_INVALPOINTER: S := 'LINEERR_INVALPOINTER';
  283.      LINEERR_REINIT: S := 'LINEERR_REINIT - (try again)';
  284.      LINEERR_NODRIVER: S := 'LINEERR_NODRIVER';
  285.      LINEERR_NODEVICE: S := 'LINEERR_NODEVICE';
  286.      LINEERR_NOMEM: S := 'LINEERR_NOMEM';
  287.      LINEERR_NOMULTIPLEINSTANCE: S := 'LINEERR_NOMULTIPLEINSTANCE';
  288.   else
  289.      S := 'Unknown Reason (' + IntToStr(ErrNo) + ')';
  290.   end;
  291.  
  292.   // show how many devices available
  293.   Memo.Lines.Add('Devices available: ' + IntToStr(FNumDevs));
  294.   
  295.   if (ErrNo <> 0) then begin
  296.      Memo.Lines.Add('LineInitialize failed with error: ' + S);
  297.      Exit;
  298.   end
  299.   else
  300.      ErrNo := LineNegotiateAPIVersion(FLineApp, FDev, Ver, Ver,
  301.         @FVersion, @FExt);
  302.   if (ErrNo <> 0) then begin
  303.      case ErrNo of
  304.         LINEERR_BADDEVICEID: S := 'LINEERR_BADDEVICEID';
  305.         LINEERR_NODRIVER: S := 'LINEERR_NODRIVER';
  306.         LINEERR_INCOMPATIBLEAPIVERSION: S :=
  307.             'LINEERR_INCOMPATIBLEAPIVERSION';
  308.         LINEERR_OPERATIONFAILED: S := 'LINEERR_OPERATIONFAILED';
  309.         LINEERR_INVALAPPHANDLE: S := 'LINEERR_INVALAPPHANDLE';
  310.         LINEERR_RESOURCEUNAVAIL: S := 'LINEERR_RESOURCEUNAVAIL';
  311.         LINEERR_INVALPOINTER: S := 'LINEERR_INVALPOINTER';
  312.         LINEERR_UNINITIALIZED: S := 'LINEERR_UNINITIALIZED';
  313.         LINEERR_NOMEM: S := 'LINEERR_NOMEM';
  314.         LINEERR_OPERATIONUNAVAIL: S := 'LINEERR_OPERATIONUNAVAIL';
  315.         LINEERR_NODEVICE: S := 'LINEERR_NODEVICE';
  316.      else
  317.         S := 'Unknown Reason (' + IntToStr(ErrNo) + ')';
  318.      end;
  319.      LineShutDown(FLineApp);
  320.      Memo.Lines.Add('LineNegotiateAPIVersion failed with error: ' + S);
  321.   end
  322.   else begin
  323.      FDev := cboxDevices.ItemIndex; // synch FDev with the combobox
  324.      Result := true;
  325.   end;
  326. end;
  327.  
  328. procedure TForm1.FormCreate(Sender: TObject);
  329. var
  330.   S: string;
  331. begin
  332.   //  added by Alan 23 Jan 98
  333.   ImageList := TImageList.Create(Application);
  334.   // added 11 Jan 98
  335.   // ===========================================================
  336.   S := ExtractFilePath(Application.exename);
  337.   // Added by Alan April 19, 1998
  338.   FTapiInitialized := false;
  339.   // FCommStatusThread.Create(true);
  340.   // Above Changed by Alan, 23 Jan 98
  341.   FCommStatusThread := TCommStatus.Create(true); // create thread suspended
  342.   // load the ImageList
  343.   with ImageList do begin
  344.      FileLoad(rtBitMap, S + 'LEDOff.bmp', clNone);      // 0
  345.      FileLoad(rtBitMap, S + 'LEDRedOn.bmp', clNone);    // 1
  346.      FileLoad(rtBitMap, S + 'LEDYellowOn.bmp', clNone); // 2
  347.      FileLoad(rtBitMap, S + 'LEDGreenOn.bmp', clNone);  // 3
  348.   end;
  349.   with ImageList do begin
  350.      GetBitMap(off, RI.Picture.Bitmap);
  351.      GetBitMap(off, CD.Picture.Bitmap);
  352.      GetBitMap(off, RD.Picture.Bitmap);
  353.      GetBitMap(off, DSR.Picture.Bitmap);
  354.      GetBitMap(off, DTR.Picture.Bitmap);
  355.      GetBitMap(off, CTS.Picture.Bitmap);
  356.      GetBitMap(off, Port.Picture.Bitmap);
  357.   end;
  358.   FMediaMode  := LINEMEDIAMODE_DATAMODEM;
  359.   FBearerMode := LINEBEARERMODE_VOICE; /// changed from speech
  360.   cboxMediaMode.ItemIndex := 3; // default to LINEMEDIAMODE_DATAMODEM
  361.   cboxBearerMode.ItemIndex := 0; // default to LINEBEARERMODE_VOICE
  362.   // ===========================================================================
  363.   FDev := 0; // default device
  364.   FLineOpen := false;
  365.   btnHangup.Enabled := false; // disable the hangup button
  366.   if not TapiInitialize then begin
  367.      Memo.Clear;
  368.      Memo.Lines.Add('Failed to initialize TAPI');
  369.      btnHangup.Enabled := false; // disable the hangup button
  370.      btnDial.Enabled := false;   // disable the dial button
  371.   end
  372.   else begin
  373.      { fill the LineCallParams structure with default values.
  374.        Mandatory for data calls, optional for voice calls }
  375.         with FLineCallParams do begin
  376.         dwTotalSize := sizeof(FLineCallParams);
  377.         dwBearerMode := FBearerMode;;
  378.         dwMediaMode := FMediaMode;
  379.      end;
  380.      // fill the combobox with the available devices
  381.      EnumerateDevices;
  382.      StatusBar.Caption := cboxDevices.Text;
  383.   end;
  384. end;
  385.  
  386. procedure TForm1.btnHangupClick(Sender: TObject);
  387. begin
  388.   if not ShutdownCallManager then
  389.      Exit;
  390. end;
  391.  
  392. procedure TForm1.CreateCallManager;
  393. var
  394.   S: string;
  395.   ErrNo: longint;
  396. begin
  397.   Memo.Clear;
  398.   if not FLineOpen then // if a line is open, no need to initialize TAPI
  399.      if not TapiInitialize then begin
  400.         Memo.Lines.Add('Failed to initialize TAPI');
  401.         Exit;
  402.      end;
  403.  
  404.   // open a line and get the line handle
  405.   if cbLineMapper.Checked then // automatically select the device
  406.      ErrNo := LineOpen(FLineApp, LINEMAPPER, @FLine, FVersion, 0, 0,
  407.         LINECALLPRIVILEGE_NONE, FMediaMode, @FLineCallParams)
  408.         // added FMediaMode 14 Jan 98
  409.   else
  410.      ErrNo := LineOpen(FLineApp, FDev, @FLine, FVersion, 0, 0,
  411.         LINECALLPRIVILEGE_NONE, FMediaMode, nil); // added FMediaMode 14 Jan 98
  412.   case ErrNo of
  413.      0: begin
  414.         S := 'Line is open'; // success so drop through
  415.         FPort := GetPortHandle; // added 18 Jan 98
  416.         FCommStatusThread.Resume; // start thread
  417.           SetBitMap(Port, green);
  418.      end;
  419.      LINEERR_ALLOCATED: S := 'LINEERR_ALLOCATED';
  420.      LINEERR_BADDEVICEID: S := 'LINEERR_BADDEVICEID';
  421.      LINEERR_INCOMPATIBLEAPIVERSION: S :=
  422.        'LINEERR_INCOMPATIBLEAPIVERSION';
  423.      LINEERR_INCOMPATIBLEEXTVERSION: S :=
  424.        'LINEERR_INCOMPATIBLEEXTVERSION';
  425.      LINEERR_INVALAPPHANDLE: S := 'LINEERR_INVALAPPHANDLE';
  426.      LINEERR_INVALMEDIAMODE: S := 'LINEERR_INVALMEDIAMODE';
  427.      LINEERR_INVALPOINTER: S := 'LINEERR_INVALPOINTER';
  428.      LINEERR_INVALPRIVSELECT: S := 'LINEERR_INVALPRIVSELECT';
  429.      LINEERR_NODEVICE: S := 'LINEERR_NODEVICE';
  430.      LINEERR_LINEMAPPERFAILED: S := 'LINEERR_LINEMAPPERFAILED';
  431.      LINEERR_NODRIVER: S := 'LINEERR_NODRIVER';
  432.      LINEERR_NOMEM: S := 'LINEERR_NOMEM';
  433.      LINEERR_OPERATIONFAILED: S := 'LINEERR_OPERATIONFAILED';
  434.      LINEERR_RESOURCEUNAVAIL: S := 'LINEERR_RESOURCEUNAVAIL';
  435.      LINEERR_STRUCTURETOOSMALL: S := 'LINEERR_STRUCTURETOOSMALL';
  436.      LINEERR_UNINITIALIZED: S := 'LINEERR_UNINITIALIZED';
  437.      LINEERR_REINIT: S := 'LINEERR_REINIT';
  438.      LINEERR_OPERATIONUNAVAIL: S := 'LINEERR_OPERATIONUNAVAIL';
  439.   else
  440.      S := 'LineOpen returned an unknown value of ' + IntToStr(ErrNo);
  441.   end;
  442.   Memo.Lines.Add('LineOpen reports: ' + S);
  443.   if (ErrNo <> 0) then
  444.      Exit
  445.   else
  446.      FLineOpen := true;
  447.  
  448.   // now place the call
  449.   ErrNo := LineMakeCall(FLine, @FHCall, PChar(ePhoneNum.Text), FCountryCode,
  450.      @FLineCallParams);
  451.   case ErrNo of
  452.      0: begin
  453.         S := 'LineMakeCall succeeded'; // success
  454.         // added 11 jan 98
  455.         //  =====================================================================
  456.      end;
  457.      LINEERR_ADDRESSBLOCKED: S := 'LINEERR_ADDRESSBLOCKED';
  458.      LINEERR_BEARERMODEUNAVAIL: S := 'LINEERR_BEARERMODEUNAVAIL';
  459.      LINEERR_CALLUNAVAIL: S := 'LINEERR_CALLUNAVAIL';
  460.      LINEERR_DIALBILLING: S := 'LINEERR_DIALBILLING';
  461.      LINEERR_DIALDIALTONE: S := 'LINEERR_DIALDIALTONE';
  462.      LINEERR_DIALPROMPT: S := 'LINEERR_DIALPROMPT';
  463.      LINEERR_DIALQUIET: S := 'LINEERR_DIALQUIET';
  464.      LINEERR_INUSE: S := 'LINEERR_INUSE';
  465.      LINEERR_INVALADDRESS: S := 'LINEERR_INVALADDRESS';
  466.      LINEERR_INVALADDRESSID: S := 'LINEERR_INVALADDRESSID';
  467.      LINEERR_INVALADDRESSMODE: S := 'LINEERR_INVALADDRESSMODE';
  468.      LINEERR_INVALBEARERMODE: S := 'LINEERR_INVALBEARERMODE';
  469.      LINEERR_INVALCALLPARAMS: S := 'LINEERR_INVALCALLPARAMS';
  470.      LINEERR_INVALCOUNTRYCODE: S := 'LINEERR_INVALCOUNTRYCODE';
  471.      LINEERR_INVALLINEHANDLE: S := 'LINEERR_INVALLINEHANDLE';
  472.      LINEERR_INVALLINESTATE: S := 'LINEERR_INVALLINESTATE';
  473.      LINEERR_INVALMEDIAMODE: S := 'LINEERR_INVALMEDIAMODE';
  474.      LINEERR_INVALPARAM: S := 'LINEERR_INVALPARAM';
  475.      LINEERR_INVALPOINTER: S := 'LINEERR_INVALPOINTER';
  476.      LINEERR_INVALRATE: S := 'LINEERR_INVALRATE';
  477.      LINEERR_NOMEM: S := 'LINEERR_NOMEM';
  478.      LINEERR_OPERATIONFAILED: S := 'LINEERR_OPERATIONFAILED';
  479.      LINEERR_OPERATIONUNAVAIL: S := 'LINEERR_OPERATIONUNAVAIL';
  480.      LINEERR_RATEUNAVAIL: S := 'LINEERR_RATEUNAVAIL';
  481.      LINEERR_RESOURCEUNAVAIL: S := 'LINEERR_RESOURCEUNAVAIL';
  482.      LINEERR_STRUCTURETOOSMALL: S := 'LINEERR_STRUCTURETOOSMALL';
  483.      LINEERR_UNINITIALIZED: S := 'LINEERR_UNINITIALIZED';
  484.      LINEERR_USERUSERINFOTOOBIG: S := 'LINEERR_USERUSERINFOTOOBIG';
  485.   else
  486.      S := 'LineMakeCall returned an unknown value (' + IntToStr(ErrNo) + ')';
  487.   end;
  488.   Memo.Lines.Add('LineMakeCall reports: ' + S);
  489. end;
  490.  
  491. function TForm1.ShutdownCallManager: boolean;
  492. var
  493.   S: string;
  494. begin
  495.   Result := false;
  496.   case LineShutdown(FLineApp) of
  497.      0: begin
  498.         S := 'success!';
  499.         { LineShutDown performs the equivalent of LineClose
  500.           so set the line flag to false }
  501.         FLineOpen := false;
  502.         btnHangup.Enabled := false;   // disable the hangup button
  503.         btnDial.Enabled := true;      // enable the dial button
  504.         Result := true;
  505.         // added 11 jan 98
  506.         ModemOff;
  507.         FCommStatusThread.Terminate;
  508.         // =====================================================================
  509.      end;
  510.      LINEERR_INVALAPPHANDLE: S := 'LINEERR_INVALAPPHANDLE';
  511.      LINEERR_NOMEM: S := 'LINEERR_NOMEM';
  512.      LINEERR_UNINITIALIZED: S := 'LINEERR_UNINITIALIZED';
  513.      LINEERR_RESOURCEUNAVAIL: S := 'LINEERR_RESOURCEUNAVAIL';
  514.   else
  515.      S := 'Unknown value';
  516.   end;
  517.   Memo.Lines.Add('LineShutDown reports: ' + S);
  518. end;
  519.  
  520. procedure TForm1.EnumerateDevices;
  521. var
  522.   i, rc: integer;
  523.   AllocSize: Integer;
  524.   LineDevCaps: LPLINEDEVCAPS; // a pointer of TLineDevCaps type
  525. begin
  526.   AllocSize := SizeOf(TLINEDEVCAPS);// + 512;
  527.   for i := 0 to FNumDevs - 1 do begin
  528.      LineDevCaps := AllocMem(AllocSize); // This will also fill with zeroes
  529.      try
  530.         // Get dev caps
  531.         LineDevCaps^.dwTotalSize := AllocSize;
  532.         rc := LineGetDevCaps(FLineApp, i, FVersion, 0, LineDevCaps);
  533.         if (LineDevCaps^.dwNeededSize > LineDevCaps^.dwTotalSize) then begin
  534.            // Buffer too small; reallocate and try again
  535.            AllocSize := LineDevCaps^.dwNeededSize;
  536.            ReallocMem(LineDevCaps, AllocSize);
  537.            LineDevCaps^.dwTotalSize := AllocSize;
  538.            rc := LineGetDevCaps(FLineApp, i, FVersion, 0, LineDevCaps);
  539.         end;
  540.         TapiCheck(rc);  // Raises exception if rc indicates a line error
  541.         // Extract line name
  542.         if (LineDevCaps^.dwStringFormat = STRINGFORMAT_ASCII) then
  543.            cboxDevices.Items.Add(RecordGetStr(LineDevCaps^,
  544.               @LineDevCaps^.dwLineNameSize))
  545.         else
  546.            cboxDevices.Items.Add('Invalid string format');
  547.      finally
  548.         FreeMem(LineDevCaps);
  549.      end;
  550.   end;
  551. end;
  552.  
  553. procedure TForm1.cboxDevicesChange(Sender: TObject);
  554. begin
  555.   FDev := cboxDevices.ItemIndex;
  556.   StatusBar.Caption := cboxDevices.Text;
  557. end;
  558.  
  559. procedure TForm1.cbLineMapperClick(Sender: TObject);
  560. begin
  561.   cboxDevices.Enabled := not cbLineMapper.Checked;
  562.   if cbLineMapper.Checked then
  563.      FDev := 0
  564.   else
  565.      FDev := cboxDevices.ItemIndex;
  566. end;
  567.  
  568. procedure TForm1.ModemOff;
  569. // sets panel to show all modem lights off
  570. begin
  571.   SetBitMap(RI, off);
  572.   SetBitMap(CD, off);
  573.   SetBitMap(RD, off);
  574.   SetBitMap(DSR, off);
  575.   SetBitMap(DTR, off);
  576.   SetBitMap(CTS, off);
  577.   SetBitMap(Port, off);
  578. end;
  579.  
  580. procedure TForm1.cboxMediaModeChange(Sender: TObject);
  581. begin
  582.   case cboxMediaMode.ItemIndex of
  583.      0:  FMediaMode := LINEMEDIAMODE_UNKNOWN;
  584.      1:  FMediaMode := LINEMEDIAMODE_INTERACTIVEVOICE;
  585.      2:  FMediaMode := LINEMEDIAMODE_AUTOMATEDVOICE;
  586.      3:  FMediaMode := LINEMEDIAMODE_DATAMODEM;
  587.      4:  FMediaMode := LINEMEDIAMODE_G3FAX;
  588.      5:  FMediaMode := LINEMEDIAMODE_TDD;
  589.      6:  FMediaMode := LINEMEDIAMODE_G4FAX;
  590.      7:  FMediaMode := LINEMEDIAMODE_DIGITALDATA;
  591.      8:  FMediaMode := LINEMEDIAMODE_TELETEX;
  592.      9:  FMediaMode := LINEMEDIAMODE_VIDEOTEX;
  593.      10: FMediaMode := LINEMEDIAMODE_TELEX;
  594.      11: FMediaMode := LINEMEDIAMODE_MIXED;
  595.      12: FMediaMode := LINEMEDIAMODE_ADSI;
  596.      13: FMediaMode := LINEMEDIAMODE_VOICEVIEW;
  597.   else
  598.      FMediaMode := LINEMEDIAMODE_INTERACTIVEVOICE; // safety valve
  599.   end;
  600.   FLineCallParams.dwMediaMode := FMediaMode;
  601. end;
  602.  
  603. procedure TForm1.cboxBearerModeChange(Sender: TObject);
  604. begin
  605.   case cboxBearerMode.ItemIndex of
  606.      0: FBearerMode := LINEBEARERMODE_VOICE;
  607.      1: FBearerMode := LINEBEARERMODE_SPEECH;
  608.      2: FBearerMode := LINEBEARERMODE_MULTIUSE;
  609.      3: FBearerMode := LINEBEARERMODE_DATA;
  610.      4: FBearerMode := LINEBEARERMODE_ALTSPEECHDATA;
  611.      5: FBearerMode := LINEBEARERMODE_NONCALLSIGNALING;
  612.      6: FBearerMode := LINEBEARERMODE_PASSTHROUGH;
  613.   else
  614.      FBearerMode := LINEBEARERMODE_SPEECH; // safety valve
  615.   end;
  616.   FLineCallParams.dwBearerMode := FBearerMode;
  617. end;
  618.  
  619. procedure TForm1.SetBitmap(Image: TImage; Index: integer);
  620. var
  621.   Bmp: TBitMap;
  622. begin
  623.   Bmp := TBitMap.Create;
  624.   try
  625.      ImageList.GetBitMap(Index, Bmp);
  626.      Image.Picture.Bitmap := Bmp;
  627.   finally
  628.     Bmp.Free;
  629.   end;
  630. end;
  631.  
  632. function TForm1.GetPortHandle : THandle;
  633. { code courtesy of Keith Anderson, Keith@PureScience.com
  634.   This code returns the port handle required to pass to SetCommMask,
  635.   GetCommModemStatus and any other low level comm functions }
  636. type
  637.   LPPort = ^TPort;
  638.      TPort = record
  639.           VarString: TVarString;
  640.           hComm: THandle;
  641.           szDeviceName: array [1..1] of Char;
  642.      end;
  643. var
  644.   Port: LPPort;
  645.   PortSize: LongInt;
  646.   FError: longint;
  647. begin
  648.   result := 0;
  649.      if not fLineOpen then exit;
  650.      PortSize := sizeof(TPort);
  651.      GetMem(Port, PortSize);
  652.      Port^.VarString.dwTotalSize := PortSize;
  653.      try
  654.           repeat
  655.             FError := lineGetID(FLine, 0, FHCall, LINECALLSELECT_LINE,
  656.               lpVarString(Port), 'comm');
  657.               if FError < 0 then exit;
  658.               if (Port^.VarString.dwNeededSize > Port^.VarString.dwTotalSize)
  659.                  then begin
  660.                  PortSize := Port^.VarString.dwNeededSize;
  661.                  FreeMem(Port);
  662.                  GetMem(Port, PortSize);
  663.                  Port^.VarString.dwTotalSize := PortSize;
  664.                  FError := -1;
  665.                  end;
  666.           until FError = 0;
  667.           Result := Port^.hComm;
  668.   finally
  669.     FreeMem(Port);
  670.   end;
  671. end;
  672.  
  673. // Added by Alan 19 April 1998
  674. procedure TForm1.ShowLineTranslateDialog(Sender: TObject);
  675. var
  676. TapiResult : word;
  677. TempNumber : string;
  678. begin
  679.   TempNumber := '+1' + Copy(ePhoneNum.Text, 2, Length(ePhoneNum.Text)-1);
  680.   if  FDev<0 then
  681.   TapiResult := lineTranslateDialogA(FLineApp, 0, ver, Application.Handle,
  682.         LPCStr(TempNumber))
  683.   else
  684.   TapiResult := lineTranslateDialogA(FLineAPP, FDev, ver, Application.Handle,
  685.         LPCStr(TempNumber));
  686.   if TapiResult<>0 then
  687.   Application.MessageBox('Could not show Line Translate Dialog Box',
  688.       'Error Opening Line Translate Dialog', MB_OK + MB_ICONERROR)
  689.   else
  690.    lineTranslateAddress(FLineAPP, FDev, ver, FCanonicalPhNum, 0,
  691.          FLineTranslateOptions, lpTranslateOutput);
  692. end;
  693.  
  694. procedure TForm1.btnDialingPropertiesClick(Sender: TObject);
  695. begin
  696.   ShowLineTranslateDialog(Sender);
  697. end;
  698.  
  699. end.
  700.